package com.ycz.sas.jgen.ui;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Enumeration;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JCheckBox;
import javax.swing.JTree;
import javax.swing.SwingWorker;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;

import com.ycz.sas.jgen.domain.CheckBoxFileTreeNode;

public class CheckBoxFileTree extends JTree {

	public static final boolean DIRECTORY_AND_FILE = true;// 含有文件节点
	public static final boolean DIRECTORY_NO_FILE = false;// 不含有文件节点
	private static final String DESKTOP_EN = "Desktop";
	private static final String DESKTOP_ZH = "桌面";

	private CheckBoxFileTreeNode systemNode = null;
	private CheckBoxFileTreeNode rootNode;
	private DefaultTreeModel jFileTreeModel;
	private boolean model;// 显示文件或不显示文件

	public CheckBoxFileTree() throws FileNotFoundException {
		this(DIRECTORY_AND_FILE);
	}

	public CheckBoxFileTree(boolean model) {
		this(null, model);
	}

	public CheckBoxFileTree(File file) {
		this(file, DIRECTORY_AND_FILE);
	}

	public CheckBoxFileTree(File file, boolean model) {
		this.model = model;
		putClientProperty("JTree.lineStyle", "Angled");
		// 建立默认系统文件树
		if (file == null || !file.exists()) {
			file = new File(System.getProperty("user.home") + File.separator
					+ DESKTOP_EN);
			if (!file.exists()) {
				file = new File(System.getProperty("user.home")
						+ File.separator + DESKTOP_ZH);
			}
			rootNode = systemNode = new CheckBoxFileTreeNode(file, model);
		} else {
			rootNode = new CheckBoxFileTreeNode(file, model);
		}

		jFileTreeModel = new DefaultTreeModel(rootNode);
		load(rootNode, file);
		setModel(jFileTreeModel);
		setCellRenderer(new CheckBoxTreeCellRenderer());
//		addTreeExpansionListener(new JTreeExpansionListener());
		addCheckingListener();
		expandAll(new TreePath(rootNode), true);
		repaint();
	}

	public CheckBoxFileTreeNode getRootNode(){
		return rootNode;
	}

	private void addCheckingListener() {
		addMouseListener(new MouseAdapter() {

			@Override
			public void mousePressed(MouseEvent e) {

				int row = getRowForLocation(e.getX(), e.getY());
				TreePath treePath = getPathForRow(row);
				if (treePath == null)
					return;
				CheckBoxFileTreeNode node = (CheckBoxFileTreeNode) treePath
						.getLastPathComponent();
				boolean checking = !node.isChecked();
				//改变节点状态自动更新到子节点上
				checkNode(node, checking);
				//选中节点自动选中所有父节点
				if(checking)
					checkNode1(node, checking);
				repaint();
				expandAll(treePath, true);

			}

		});
	}

	public void expandAll(TreePath parent, boolean expand) {
		if(expand)
			expandPath(parent);
		else
			collapsePath(parent);
		CheckBoxFileTreeNode node = (CheckBoxFileTreeNode) parent.getLastPathComponent();
		if(node.getChildCount() > 0 ){
			for (Enumeration<CheckBoxFileTreeNode> children = node.children();
						children.hasMoreElements();) {
				CheckBoxFileTreeNode child = children.nextElement();
				TreePath path = parent.pathByAddingChild(child);
				expandAll(path, expand);
			}
		}
	}

	private void checkNode(CheckBoxFileTreeNode node, boolean checking) {
		node.setChecked(checking);
		node.setUpdate(false);
		if (!node.isLeaf()) {
			Enumeration<CheckBoxFileTreeNode> children = node.children();
			while (children.hasMoreElements()) {
				CheckBoxFileTreeNode checkBoxTreeNode = (CheckBoxFileTreeNode) children
						.nextElement();
				checkNode(checkBoxTreeNode, checking);
			}
		}
	}

	private void checkNode1(CheckBoxFileTreeNode node, boolean checking) {
		node.setChecked(checking);
		node.setUpdate(false);
		if (!node.isRoot()) {
			CheckBoxFileTreeNode parent = (CheckBoxFileTreeNode) node.getParent();
			checkNode1(parent, checking);
		}
	}


	private void load(CheckBoxFileTreeNode parent, File file){
		File[] files = file.listFiles();
		if (files == null) {
			return ;
		}
		for (int i = 0; i < files.length; i++) {
			File f = files[i];
			/**
			 * 文件夹必添加 文件则受系统文件树model控制
			 */
			if ((f.isDirectory() || model )&& !f.getName().equalsIgnoreCase(".svn")) {
				CheckBoxFileTreeNode curnode = new CheckBoxFileTreeNode(f, model);
				parent.add(curnode);
				load(curnode, f);
			}
		}
	}


	public String getPathName(TreePath path) {
		Object o = path.getLastPathComponent();
		if (o instanceof CheckBoxFileTreeNode) {
			return ((CheckBoxFileTreeNode) o).file.getAbsolutePath();
		}
		return null;
	}


	protected class JTreeExpansionListener implements TreeExpansionListener {
		public void treeExpanded(TreeExpansionEvent e) {
			CheckBoxFileTreeNode fileNode = (CheckBoxFileTreeNode) e.getPath()
					.getLastPathComponent();
			if (fileNode != null) {
				new FileNodeExpansion(fileNode).execute();
			}
		}

		public void treeCollapsed(TreeExpansionEvent e) {
		}
	}

	protected class FileNodeExpansion extends SwingWorker<Boolean, Void> {
		private CheckBoxFileTreeNode node;

		public FileNodeExpansion(CheckBoxFileTreeNode node) {
			this.node = node;
		}

		@Override
		protected Boolean doInBackground() throws Exception {
			return node.expand();
		}

		@Override
		protected void done() {
			try {
				// 节点可以展开
				if (get()) {
					jFileTreeModel.reload(node);
				}
			} catch (InterruptedException ex) {
				Logger.getLogger(CheckBoxFileTree.class.getName()).log(
						Level.SEVERE, null, ex);
			} catch (ExecutionException ex) {
				Logger.getLogger(CheckBoxFileTree.class.getName()).log(
						Level.SEVERE, null, ex);
			}
		}
	}

	protected class CheckBoxTreeCellRenderer implements TreeCellRenderer {
		private JCheckBox renderer = new JCheckBox();

		Color selectionBorderColor, selectionForeground, selectionBackground,
				textForeground, textBackground;

		protected JCheckBox getRenderer() {
			return renderer;
		}

		public CheckBoxTreeCellRenderer() {
			setOpaque(false);
		}

		@Override
		public Component getTreeCellRendererComponent(JTree tree, Object value,
				boolean selected, boolean expanded, boolean leaf, int row,
				boolean hasFocus) {
			CheckBoxFileTreeNode node = (CheckBoxFileTreeNode) value;

			renderer.setText(node.toString());
			if (node.isChecked) {
				renderer.setSelected(true);
				renderer.setForeground(Color.yellow);
				renderer.setBackground(node.getSelectedBackground());
				if (node.isUpdate()) {
					renderer.setBackground(node.getUpdateBackground());
				}
			} else {
				renderer.setSelected(false);
				renderer.setForeground(tree.getForeground());
				renderer.setBackground(tree.getBackground());
			}
			return renderer;
		}

	}

}
